View Javadoc

1   /***
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Exoffice Technologies.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Exoffice Technologies. Exolab is a registered
23   *    trademark of Exoffice Technologies.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: ORBRemoteContext.java,v 1.1 2005/11/18 03:29:41 tanderson Exp $
44   */
45  package org.exolab.jms.jndi;
46  
47  import java.util.Hashtable;
48  import java.util.NoSuchElementException;
49  import javax.naming.Binding;
50  import javax.naming.Context;
51  import javax.naming.Name;
52  import javax.naming.NameParser;
53  import javax.naming.NamingEnumeration;
54  import javax.naming.NamingException;
55  
56  import org.codehaus.spice.jndikit.RemoteContext;
57  import org.exolab.jms.net.proxy.Proxy;
58  
59  
60  /***
61   * <code>Context</code> implementation that reference counts the
62   * underlying provider.
63   *
64   * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
65   * @version $Revision: 1.1 $ $Date: 2005/11/18 03:29:41 $
66   */
67  class ORBRemoteContext implements Context {
68  
69      /***
70       * Environment key for the naming provider reference counter.
71       */
72      private static String REFERENCE_KEY = "NamingProviderReferenceCounter";
73  
74      /***
75       * The context.
76       */
77      private RemoteContext _context;
78  
79  
80      /***
81       * Construct a new <code>ORBRemoteContext</code>.
82       *
83       * @param context the context to delegate requests to
84       * @throws NamingException for any error
85       */
86      public ORBRemoteContext(RemoteContext context) throws NamingException {
87          _context = context;
88          reference();
89      }
90  
91      /***
92       * Retrieves the named object.
93       *
94       * @param name the name of the object to look up
95       * @return	the object bound to <tt>name</tt>
96       * @throws	NamingException if a naming exception is encountered
97       */
98      public Object lookup(Name name) throws NamingException {
99          return wrap(_context.lookup(name));
100     }
101 
102     /***
103      * Retrieves the named object.
104      *
105      * @param name the name of the object to look up
106      * @return	the object bound to <tt>name</tt>
107      * @throws	NamingException if a naming exception is encountered
108      */
109     public Object lookup(String name) throws NamingException {
110         return wrap(_context.lookup(name));
111     }
112 
113     /***
114      * Binds a name to an object.
115      *
116      * @param name the name to bind; may not be empty
117      * @param obj  the object to bind; possibly null
118      * @throws	NamingException if a naming exception is encountered
119      */
120     public void bind(Name name, Object obj) throws NamingException {
121         _context.bind(name, obj);
122     }
123 
124     /***
125      * Binds a name to an object.
126      *
127      * @param name the name to bind; may not be empty
128      * @param obj  the object to bind; possibly null
129      * @throws	NamingException if a naming exception is encountered
130      */
131     public void bind(String name, Object obj) throws NamingException {
132         _context.bind(name, obj);
133     }
134 
135     /***
136      * Binds a name to an object, overwriting any existing binding.
137      *
138      * @param name the name to bind; may not be empty
139      * @param obj  the object to bind; possibly null
140      * @throws	NamingException if a naming exception is encountered
141      */
142     public void rebind(Name name, Object obj) throws NamingException {
143         _context.rebind(name, obj);
144     }
145 
146     /***
147      * Binds a name to an object, overwriting any existing binding.
148      *
149      * @param name the name to bind; may not be empty
150      * @param obj  the object to bind; possibly null
151      * @throws	NamingException if a naming exception is encountered
152      */
153     public void rebind(String name, Object obj) throws NamingException {
154         _context.rebind(name, obj);
155     }
156 
157     /***
158      * Unbinds the named object.
159      *
160      * @param name the name to unbind; may not be empty
161      * @throws	NamingException if a naming exception is encountered
162      */
163     public void unbind(Name name) throws NamingException {
164         _context.unbind(name);
165     }
166 
167     /***
168      * Unbinds the named object.
169      *
170      * @param name the name to unbind; may not be empty
171      * @throws	NamingException if a naming exception is encountered
172      */
173     public void unbind(String name) throws NamingException {
174         _context.unbind(name);
175     }
176 
177     /***
178      * Binds a new name to the object bound to an old name, and unbinds
179      * the old name.
180      *
181      * @param oldName the name of the existing binding; may not be empty
182      * @param newName the name of the new binding; may not be empty
183      * @throws	NamingException if a naming exception is encountered
184      */
185     public void rename(Name oldName, Name newName) throws NamingException {
186         _context.rename(oldName, newName);
187     }
188 
189     /***
190      * Binds a new name to the object bound to an old name, and unbinds
191      * the old name.
192      *
193      * @param oldName the name of the existing binding; may not be empty
194      * @param newName the name of the new binding; may not be empty
195      * @throws	NamingException if a naming exception is encountered
196      */
197     public void rename(String oldName, String newName) throws NamingException {
198         _context.rename(oldName, newName);
199     }
200 
201     /***
202      * Enumerates the names bound in the named context, along with the
203      * class names of objects bound to them.
204      *
205      * @param name the name of the context to list
206      * @return	an enumeration of the names and class names of the
207      * bindings in this context.  Each element of the
208      * enumeration is of type <tt>NameClassPair</tt>.
209      * @throws	NamingException if a naming exception is encountered
210      */
211     public NamingEnumeration list(Name name) throws NamingException {
212         return _context.list(name);
213     }
214 
215     /***
216      * Enumerates the names bound in the named context, along with the
217      * class names of objects bound to them.
218      *
219      * @param name the name of the context to list
220      * @return	an enumeration of the names and class names of the
221      * bindings in this context.  Each element of the
222      * enumeration is of type <tt>NameClassPair</tt>.
223      * @throws	NamingException if a naming exception is encountered
224      */
225     public NamingEnumeration list(String name) throws NamingException {
226         return _context.list(name);
227     }
228 
229     /***
230      * Enumerates the names bound in the named context, along with the
231      * objects bound to them.
232      *
233      * @param name the name of the context to list
234      * @return	an enumeration of the bindings in this context.
235      * Each element of the enumeration is of type
236      * <tt>Binding</tt>.
237      * @throws	NamingException if a naming exception is encountered
238      */
239     public NamingEnumeration listBindings(Name name) throws NamingException {
240         return new ORBNamingEnumeration(_context.listBindings(name));
241     }
242 
243     /***
244      * Enumerates the names bound in the named context, along with the
245      * objects bound to them.
246      *
247      * @param name the name of the context to list
248      * @return	an enumeration of the bindings in this context.
249      * Each element of the enumeration is of type
250      * <tt>Binding</tt>.
251      * @throws	NamingException if a naming exception is encountered
252      */
253     public NamingEnumeration listBindings(String name) throws NamingException {
254         return _context.listBindings(name);
255     }
256 
257     /***
258      * Destroys the named context and removes it from the namespace.
259      *
260      * @param name the name of the context to be destroyed; may not be empty
261      * @throws	NamingException if a naming exception is encountered
262      */
263     public void destroySubcontext(Name name) throws NamingException {
264         _context.destroySubcontext(name);
265     }
266 
267     /***
268      * Destroys the named context and removes it from the namespace.
269      *
270      * @param name the name of the context to be destroyed; may not be empty
271      * @throws	NamingException if a naming exception is encountered
272      */
273     public void destroySubcontext(String name) throws NamingException {
274         _context.destroySubcontext(name);
275     }
276 
277     /***
278      * Creates and binds a new context.
279      *
280      * @param name the name of the context to create; may not be empty
281      * @return	the newly created context
282      * @throws	NamingException if a naming exception is encountered
283      */
284     public Context createSubcontext(Name name) throws NamingException {
285         return (Context) wrap(_context.createSubcontext(name));
286     }
287 
288     /***
289      * Creates and binds a new context.
290      *
291      * @param name the name of the context to create; may not be empty
292      * @return	the newly created context
293      * @throws	NamingException if a naming exception is encountered
294      */
295     public Context createSubcontext(String name) throws NamingException {
296         return (Context) wrap(_context.createSubcontext(name));
297     }
298 
299     /***
300      * Retrieves the named object, following links except
301      * for the terminal atomic component of the name.
302      *
303      * @param name the name of the object to look up
304      * @return	the object bound to <tt>name</tt>, not following the
305      * terminal link (if any).
306      * @throws	NamingException if a naming exception is encountered
307      */
308     public Object lookupLink(Name name) throws NamingException {
309         return wrap(_context.lookupLink(name));
310     }
311 
312     /***
313      * Retrieves the named object, following links except
314      * for the terminal atomic component of the name.
315      *
316      * @param name the name of the object to look up
317      * @return	the object bound to <tt>name</tt>, not following the
318      * terminal link (if any)
319      * @throws	NamingException if a naming exception is encountered
320      */
321     public Object lookupLink(String name) throws NamingException {
322         return wrap(_context.lookupLink(name));
323     }
324 
325     /***
326      * Retrieves the parser associated with the named context.
327      *
328      * @param name the name of the context from which to get the parser
329      * @return	a name parser that can parse compound names into their atomic
330      * components
331      * @throws	NamingException if a naming exception is encountered
332      */
333     public NameParser getNameParser(Name name) throws NamingException {
334         return _context.getNameParser(name);
335     }
336 
337     /***
338      * Retrieves the parser associated with the named context.
339      *
340      * @param name the name of the context from which to get the parser
341      * @return	a name parser that can parse compound names into their atomic
342      * components
343      * @throws	NamingException if a naming exception is encountered
344      */
345     public NameParser getNameParser(String name) throws NamingException {
346         return _context.getNameParser(name);
347     }
348 
349     /***
350      * Composes the name of this context with a name relative to
351      * this context.
352      *
353      * @param name   a name relative to this context
354      * @param prefix the name of this context relative to one of its ancestors
355      * @return	the composition of <code>prefix</code> and <code>name</code>
356      * @throws	NamingException if a naming exception is encountered
357      */
358     public Name composeName(Name name, Name prefix) throws NamingException {
359         return _context.composeName(name, prefix);
360     }
361 
362     /***
363      * Composes the name of this context with a name relative to
364      * this context.
365      *
366      * @param name   a name relative to this context
367      * @param prefix the name of this context relative to one of its ancestors
368      * @return	the composition of <code>prefix</code> and <code>name</code>
369      * @throws	NamingException if a naming exception is encountered
370      */
371     public String composeName(String name, String prefix)
372             throws NamingException {
373         return _context.composeName(name, prefix);
374     }
375 
376     /***
377      * Adds a new environment property to the environment of this
378      * context.  If the property already exists, its value is overwritten.
379      *
380      * @param propName the name of the environment property to add; may not be null
381      * @param propVal  the value of the property to add; may not be null
382      * @return	the previous value of the property, or null if the property was
383      * not in the environment before
384      * @throws	NamingException if a naming exception is encountered
385      */
386     public Object addToEnvironment(String propName, Object propVal)
387             throws NamingException {
388         return _context.addToEnvironment(propName, propVal);
389     }
390 
391     /***
392      * Removes an environment property from the environment of this
393      * context.  See class description for more details on environment
394      * properties.
395      *
396      * @param propName the name of the environment property to remove; may not be null
397      * @return	the previous value of the property, or null if the property was
398      * not in the environment
399      * @throws	NamingException if a naming exception is encountered
400      */
401     public Object removeFromEnvironment(String propName)
402             throws NamingException {
403         return _context.removeFromEnvironment(propName);
404     }
405 
406     /***
407      * Retrieves the environment in effect for this context.
408      *
409      * @return	the environment of this context; never null
410      * @throws	NamingException if a naming exception is encountered
411      */
412     public Hashtable getEnvironment() throws NamingException {
413         return _context.getEnvironment();
414     }
415 
416     /***
417      * Closes this context.
418      *
419      * @throws	NamingException if a naming exception is encountered
420      */
421     public void close() throws NamingException {
422         if (_context != null) {
423             if (dereference() <= 0) {
424                 Object provider = getEnvironment().get(
425                         RemoteContext.NAMING_PROVIDER);
426                 if (provider instanceof Proxy) {
427                     ((Proxy) provider).disposeProxy();
428                 }
429             }
430             _context.close();
431             _context = null;
432         }
433     }
434 
435     /***
436      * Retrieves the full name of this context within its own namespace.
437      *
438      * @return	this context's name in its own namespace; never null
439      * @throws	NamingException if a naming exception is encountered
440      */
441     public String getNameInNamespace() throws NamingException {
442         return _context.getNameInNamespace();
443     }
444 
445     /***
446      * Called by the garbage collector on an object when garbage collection
447      * determines that there are no more references to the object.
448      *
449      * @throws Throwable the <code>Exception</code> raised by this method
450      */
451     protected void finalize() throws Throwable {
452         close();
453     }
454 
455     /***
456      * Wrap the supplied object in an <code>ORBRemoteContext</code> iff it
457      * is an instance of <code>RemoteContext</code>, otherwise returns the
458      * object unchanged.
459      *
460      * @param object the object to wrap
461      * @return the supplied object in an <code>ORBRemoteContext</code> iff it
462      * is an instance of <code>RemoteContext</code>, otherwise returns the
463      * object unchanged.
464      * @throws NamingException if a naming exception is encountered
465      */
466     private Object wrap(Object object) throws NamingException {
467         if (object instanceof RemoteContext) {
468             return new ORBRemoteContext((RemoteContext) object);
469         }
470         return object;
471     }
472 
473     /***
474      * Increment the reference count of the provider. This is the number
475      * of <code>Context</code> instances that refer to it.
476      *
477      * @throws NamingException for any naming error
478      */
479     private void reference() throws NamingException {
480         Ref ref = (Ref) _context.getEnvironment().get(REFERENCE_KEY);
481         if (ref == null) {
482             ref = new Ref();
483             _context.addToEnvironment(REFERENCE_KEY, ref);
484         }
485         ref.inc();
486     }
487 
488     /***
489      * Dereference the reference count of the provider.
490      *
491      * @return the number of references
492      * @throws NamingException for any naming error
493      */
494     private int dereference() throws NamingException {
495         Ref ref = (Ref) _context.getEnvironment().get(REFERENCE_KEY);
496         return (ref != null) ? ref.dec() : 0;
497     }
498 
499 
500     /***
501      * Helper to wrap any <code>RemoteContext</code> instances returned
502      * by a <code>NamingEnumeration</code> in <code>ORBRemoteContext</code>
503      * instances.
504      */
505     private static class ORBNamingEnumeration implements NamingEnumeration {
506 
507         /***
508          * The enumeration.
509          */
510         private final NamingEnumeration _iterator;
511 
512         /***
513          * Construct a new <code>ORBNamingEnumeration</code>.
514          *
515          * @param iterator the enumeration to delegate to
516          */
517         private ORBNamingEnumeration(NamingEnumeration iterator) {
518             _iterator = iterator;
519         }
520 
521         /***
522          * Retrieves the next element in the enumeration.
523          *
524          * @return the next element in the enumeration.
525          * @throws NamingException for any naming error
526          * @throws java.util.NoSuchElementException If attempting to get the next element when none is available.
527          */
528         public Object next() throws NamingException {
529             return wrap(_iterator.next());
530         }
531 
532         /***
533          * Determines whether there are any more elements in the enumeration.
534          *
535          * @throws NamingException for any naming error.
536          * @return		true if there is more in the enumeration; false otherwise.
537          */
538         public boolean hasMore() throws NamingException {
539             return _iterator.hasMore();
540         }
541 
542         /***
543          * Closes this enumeration.
544          *
545          * @throws NamingException for any naming error
546          */
547         public void close() throws NamingException {
548             _iterator.close();
549         }
550 
551         /***
552          * Tests if this enumeration contains more elements.
553          *
554          * @return <code>true</code> if and only if this enumeration object
555          *         contains at least one more element to provide;
556          *         <code>false</code> otherwise.
557          */
558         public boolean hasMoreElements() {
559             return _iterator.hasMoreElements();
560         }
561 
562         /***
563          * Returns the next element of this enumeration if this enumeration
564          * object has at least one more element to provide.
565          *
566          * @return the next element of this enumeration.
567          * @throws java.util.NoSuchElementException if no more elements exist.
568          */
569         public Object nextElement() {
570             try {
571                 return wrap(_iterator.nextElement());
572             } catch (NamingException exception) {
573                 throw new NoSuchElementException(exception.getMessage());
574             }
575         }
576 
577         /***
578          * Wraps any <code>Context</code> instances in <code>ORBRemoteContext</code>.
579          *
580          * @param obj the object
581          * @return obj
582          * @throws NamingException for any naming error
583          */
584         private Object wrap(Object obj) throws NamingException {
585             if (obj instanceof Binding) {
586                 Binding binding = (Binding) obj;
587                 Object bound = binding.getObject();
588                 if (bound instanceof RemoteContext) {
589                     binding.setObject(
590                             new ORBRemoteContext((RemoteContext) bound));
591                 }
592             }
593             return obj;
594         }
595     }
596 
597     /***
598      * Helper to maintain a reference count.
599      */
600     private static class Ref {
601 
602         /***
603          * The reference count.
604          */
605         private int _count;
606 
607         /***
608          * Increment the reference count.
609          *
610          * @return the reference count
611          */
612         public synchronized int inc() {
613             return ++_count;
614         }
615 
616         /***
617          * Decrement the reference count.
618          *
619          * @return the reference count
620          */
621         public synchronized int dec() {
622             return --_count;
623         }
624 
625     }
626 
627 }